postUpdateAnnexHook :: Git.Hook
postUpdateAnnexHook = Git.Hook "post-update-annex" "" []
+preInitAnnexHook :: Git.Hook
+preInitAnnexHook = Git.Hook "pre-init-annex" "" []
+
freezeContentAnnexHook :: Git.Hook
freezeContentAnnexHook = Git.Hook "freezecontent-annex" "" []
return exists
runAnnexHook :: Git.Hook -> (GitConfig -> Maybe String) -> Annex ()
-runAnnexHook hook commandcfg = ifM (doesAnnexHookExist hook)
+runAnnexHook hook commandcfg = runAnnexHook' hook commandcfg >>= \case
+ Nothing -> noop
+ Just failedcommanddesc ->
+ warning $ UnquotedString $ failedcommanddesc ++ " failed"
+
+-- Returns Nothing if the hook or GitConfig command succeeded, or a
+-- description of what failed.
+runAnnexHook' :: Git.Hook -> (GitConfig -> Maybe String) -> Annex (Maybe String)
+runAnnexHook' hook commandcfg = ifM (doesAnnexHookExist hook)
( runhook
, runcommandcfg
)
where
- runhook = unlessM (inRepo $ Git.runHook boolSystem hook []) $ do
- h <- fromRepo $ Git.hookFile hook
- commandfailed h
+ runhook = ifM (inRepo $ Git.runHook boolSystem hook [])
+ ( return Nothing
+ , do
+ h <- fromRepo (Git.hookFile hook)
+ commandfailed h
+ )
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
+ Nothing -> return Nothing
Just command ->
- unlessM (liftIO $ boolSystem "sh" [Param "-c", Param command]) $
- commandfailed command
- Nothing -> noop
- commandfailed c = warning $ UnquotedString $ c ++ " failed"
+ ifM (liftIO $ boolSystem "sh" [Param "-c", Param command])
+ ( return Nothing
+ , commandfailed $ "git configured command '" ++ command ++ "'"
+ )
+ commandfailed c = return $ Just c
runAnnexPathHook :: String -> Git.Hook -> (GitConfig -> Maybe String) -> RawFilePath -> Annex Bool
runAnnexPathHook pathtoken hook commandcfg p = ifM (doesAnnexHookExist hook)
where
runhook = inRepo $ Git.runHook boolSystem hook [ File (fromRawFilePath p) ]
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
+ Nothing -> return True
Just basecmd -> liftIO $
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
- Nothing -> return True
gencmd = massReplace [ (pathtoken, shellEscape (fromRawFilePath p)) ]
outputOfAnnexHook :: Git.Hook -> (GitConfig -> Maybe String) -> Annex (Maybe String)
runhook = inRepo (Git.runHook runhook' hook [])
runhook' c ps = Just <$> readProcess c (toCommand ps)
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
+ Nothing -> return Nothing
Just command -> liftIO $
Just <$> readProcess "sh" ["-c", command]
- Nothing -> return Nothing
{- git-annex repository initialization
-
- - Copyright 2011-2024 Joey Hess <id@joeyh.name>
+ - Copyright 2011-2025 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
checkInitializeAllowed :: (InitializeAllowed -> Annex a) -> Annex a
checkInitializeAllowed a = guardSafeToUseRepo $ noAnnexFileContent' >>= \case
- Nothing -> do
- checkSqliteWorks
- a InitializeAllowed
+ Nothing -> runAnnexHook' preInitAnnexHook annexPreInitCommand >>= \case
+ Nothing -> do
+ checkSqliteWorks
+ a InitializeAllowed
+ Just failedcommanddesc -> do
+ initpreventedby failedcommanddesc
+ notinitialized
Just noannexmsg -> do
- warning "Initialization prevented by .noannex file (remove the file to override)"
+ initpreventedby ".noannex file (remove the file to override)"
unless (null noannexmsg) $
warning (UnquotedString noannexmsg)
- giveup "Not initialized."
+ notinitialized
+ where
+ initpreventedby r = warning $ UnquotedString $
+ "Initialization prevented by " ++ r
+ notinitialized = giveup "Not initialized."
initializeAllowed :: Annex Bool
-initializeAllowed = isNothing <$> noAnnexFileContent'
+initializeAllowed = noAnnexFileContent' >>= \case
+ Nothing -> runAnnexHook' preInitAnnexHook annexPreInitCommand >>= \case
+ Nothing -> return True
+ Just _ -> return False
+ Just _ -> return False
noAnnexFileContent' :: Annex (Maybe String)
noAnnexFileContent' = inRepo $
getInitializedVersion >>= maybe needsinit checkUpgrade
where
needsinit =
- whenM (initializeAllowed <&&> check) $ do
+ whenM (check <&&> initializeAllowed) $ do
initialize startupannex Nothing Nothing
autoEnableSpecialRemotes remotelist
annex.http-headers-command.
* Added git configs annex.post-update-command and annex.pre-commit-command
that correspond to the post-update-annex and pre-commit-annex hooks.
+ * Added annex.pre-init-command git config and pre-init-annex hook
+ that is run before git-annex repository initialization.
-- Joey Hess <id@joeyh.name> Fri, 03 Jan 2025 14:30:38 -0400
, annexAlwaysCompact :: Bool
, annexCommitMessage :: Maybe String
, annexCommitMessageCommand :: Maybe String
+ , annexPreInitCommand :: Maybe String
, annexPreCommitCommand :: Maybe String
, annexPostUpdateCommand :: Maybe String
, annexMergeAnnexBranches :: Bool
, annexAlwaysCompact = getbool (annexConfig "alwayscompact") True
, annexCommitMessage = getmaybe (annexConfig "commitmessage")
, annexCommitMessageCommand = getmaybe (annexConfig "commitmessage-command")
+ , annexPreInitCommand = getmaybe (annexConfig "pre-init-command")
, annexPreCommitCommand = getmaybe (annexConfig "pre-commit-command")
, annexPostUpdateCommand = getmaybe (annexConfig "post-update-command")
, annexMergeAnnexBranches = getbool (annexConfig "merge-annex-branches") True
A top-level `.noannex` file will prevent git-annex init from being used
in a repository. This is useful for repositories that have a policy
reason not to use git-annex. The content of the file will be displayed
-to the user who tries to run git-annex init.
+to the user who tries to run git-annex init.
+
+The annex.pre-init-command git configuration or pre-init-annex hook
+is run before initialization and can exit nonzero as well to prevent
+initialization, as well as doing other setup.
# EXAMPLES
Alternatively, a hook script can be installed in
`.git/hooks/pre-commit-annex`
+* `annex.pre-init-command`
+
+ This command is run before the repository is initialized, either by
+ `git-annex init`, or automatic initialization. It can configure
+ the repository in any way needed. If it exits nonzero, the repository
+ initialization will fail.
+
+ Alternatively, a hook script can be installed in
+ `.git/hooks/pre-init-annex`
+
* `annex.alwayscompact`
By default, git-annex compacts data it records in the git-annex branch.
[[!meta author=yoh]]
[[!tag projects/openneuro]]
+
+> [[done]] --[[Joey]]
--- /dev/null
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2025-01-13T17:33:02Z"
+ content="""
+Note that the `.noannex` file that prevents init has some overlap with
+a pre-init hook that exits nonzero. I guess the .noannex file has the
+benefit of working in every clone of a repository without additional
+configuration.
+"""]]
--- /dev/null
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2025-01-13T18:17:42Z"
+ content="""
+Implemented .git/hooks/pre-init-annex
+(and alternatively git config annex.pre-init-command)
+
+Note that this is also run before automatic initialization.
+"""]]